package service

import (
	"context"
	"fmt"
	"time"

	"gitee.com/daonna/collab-manage-system/ent"
	"gitee.com/daonna/collab-manage-system/ent/conversation"
	"gitee.com/daonna/collab-manage-system/ent/conversationmember"
	"gitee.com/daonna/collab-manage-system/ent/message"
	"gitee.com/daonna/collab-manage-system/repository/db"
)

type UserInfo struct {
	ID          int64  `json:"id"`
	Username    string `json:"username"`
	DisplayName string `json:"display_name"`
	AvatarURL   string `json:"avatar_url"`
}

// ConversationResponse 会话返回结构
type ConversationResponse struct {
	ID            int64      `json:"id"`
	Type          string     `json:"type"`           // 会话类型: group, private
	Name          string     `json:"name,omitempty"` // 群聊名称
	Description   string     `json:"description,omitempty"`
	AvatarURL     string     `json:"avatar_url,omitempty"`
	CreatorID     int64      `json:"creator_id"`
	LastMessageAt *time.Time `json:"last_message_at,omitempty"`
	UnreadCount   int        `json:"unread_count"` // 未读消息数
	IsPinned      bool       `json:"is_pinned"`    // 是否置顶
	IsMuted       bool       `json:"is_muted"`     // 是否静音
	MemberCount   int        `json:"member_count"` // 成员数量
	CreatedAt     time.Time  `json:"created_at"`
	UpdatedAt     time.Time  `json:"updated_at"`

	// 单聊特有字段
	PeerUser *UserInfo `json:"peer_user,omitempty"` // 对方用户信息(单聊)
}

// ListConversations 获取用户的所有会话
func ListConversations(ctx context.Context, userID uint, conversationType string) ([]*ConversationResponse, error) {
	client := db.GetDBClient()

	// 查询用户所有会话
	query := client.ConversationMember().ConversationMember.Query().
		Where(conversationmember.UserID(int64(userID))).
		WithConversation()

	// 根据类型过滤
	if conversationType == "group" {
		query = query.WithConversation(func(q *ent.ConversationQuery) {
			q.Where(conversation.TypeEQ(conversation.TypeGroup))
		})
	} else if conversationType == "private" {
		query = query.WithConversation(func(q *ent.ConversationQuery) {
			q.Where(conversation.TypeEQ(conversation.TypePrivate))
		})
	}

	members, err := query.All(ctx)
	if err != nil {
		return nil, fmt.Errorf("查询会话失败: %w", err)
	}

	result := make([]*ConversationResponse, 0, len(members))

	for _, member := range members {
		if member.Edges.Conversation == nil {
			continue
		}

		conv := member.Edges.Conversation

		// 获取未读消息数
		// TODO: 实现未读消息计数逻辑

		response := &ConversationResponse{
			ID:            conv.ID,
			Type:          string(conv.Type),
			Name:          conv.Name,
			Description:   conv.Description,
			AvatarURL:     conv.AvatarURL,
			CreatorID:     conv.CreatorID,
			UnreadCount:   0, // TODO: 实现
			IsPinned:      member.IsPinned,
			IsMuted:       member.IsMuted,
			LastMessageAt: &conv.LastMessageAt,
			CreatedAt:     conv.CreatedAt,
			UpdatedAt:     conv.UpdatedAt,
		}

		// 获取会话成员数量
		count, err := client.ConversationMember().ConversationMember.Query().
			Where(conversationmember.ConversationID(conv.ID)).
			Count(ctx)
		if err == nil {
			response.MemberCount = count
		}

		// 如果是私聊，获取对方用户信息
		if conv.Type == conversation.TypePrivate {
			peerMember, err := client.ConversationMember().ConversationMember.Query().
				Where(
					conversationmember.ConversationID(conv.ID),
					conversationmember.UserIDNEQ(int64(userID)),
				).
				WithUser().
				Only(ctx)

			if err == nil && peerMember.Edges.User != nil {
				peerUser := peerMember.Edges.User
				response.PeerUser = &UserInfo{
					ID:          peerUser.ID,
					Username:    peerUser.Username,
					DisplayName: peerUser.DisplayName,
					AvatarURL:   peerUser.AvatarURL,
				}
			}
		}

		result = append(result, response)
	}

	return result, nil
}

// GetConversation 获取单个会话详情
func GetConversation(ctx context.Context, conversationID int64, userID uint) (*ConversationResponse, error) {
	client := db.GetDBClient()

	// 检查用户是否是会话成员
	member, err := client.ConversationMember().ConversationMember.Query().
		Where(
			conversationmember.ConversationID(conversationID),
			conversationmember.UserID(int64(userID)),
		).
		WithConversation().
		Only(ctx)

	if err != nil {
		return nil, fmt.Errorf("获取会话失败或用户不是会话成员: %w", err)
	}

	if member.Edges.Conversation == nil {
		return nil, fmt.Errorf("会话不存在")
	}

	conv := member.Edges.Conversation

	response := &ConversationResponse{
		ID:            conv.ID,
		Type:          string(conv.Type),
		Name:          conv.Name,
		Description:   conv.Description,
		AvatarURL:     conv.AvatarURL,
		CreatorID:     conv.CreatorID,
		UnreadCount:   0, // TODO: 实现
		IsPinned:      member.IsPinned,
		IsMuted:       member.IsMuted,
		LastMessageAt: &conv.LastMessageAt,
		CreatedAt:     conv.CreatedAt,
		UpdatedAt:     conv.UpdatedAt,
	}

	// 获取会话成员数量
	count, err := client.ConversationMember().ConversationMember.Query().
		Where(conversationmember.ConversationID(conv.ID)).
		Count(ctx)
	if err == nil {
		response.MemberCount = count
	}

	// 如果是私聊，获取对方信息
	if conv.Type == conversation.TypePrivate {
		peerMember, err := client.ConversationMember().ConversationMember.Query().
			Where(
				conversationmember.ConversationID(conv.ID),
				conversationmember.UserIDNEQ(int64(userID)),
			).
			WithUser().
			Only(ctx)

		if err == nil && peerMember.Edges.User != nil {
			peerUser := peerMember.Edges.User
			response.PeerUser = &UserInfo{
				ID:          peerUser.ID,
				Username:    peerUser.Username,
				DisplayName: peerUser.DisplayName,
				AvatarURL:   peerUser.AvatarURL,
			}
		}
	}

	return response, nil
}

// CreateGroupChat 创建群聊
func CreateGroupChat(ctx context.Context, creatorID uint, name, description, avatarURL string, memberIDs []uint) (*ConversationResponse, error) {
	client := db.GetDBClient()

	// 开启事务
	tx, err := client.Group().Tx(ctx)
	if err != nil {
		return nil, fmt.Errorf("开启事务失败: %w", err)
	}

	// 创建会话
	conv, err := tx.Conversation.Create().
		SetType(conversation.TypeGroup).
		SetName(name).
		SetDescription(description).
		SetAvatarURL(avatarURL).
		SetCreatorID(int64(creatorID)).
		SetLastMessageAt(time.Now()).
		Save(ctx)

	if err != nil {
		tx.Rollback()
		return nil, fmt.Errorf("创建群聊失败: %w", err)
	}

	// 添加所有成员
	for _, memberID := range memberIDs {
		role := "member"
		if memberID == creatorID {
			role = "owner"
		}

		_, err = tx.ConversationMember.Create().
			SetConversationID(conv.ID).
			SetUserID(int64(memberID)).
			SetRole(conversationmember.Role(role)).
			SetJoinedAt(time.Now()).
			Save(ctx)

		if err != nil {
			tx.Rollback()
			return nil, fmt.Errorf("添加群成员失败: %w", err)
		}
	}

	// 提交事务
	if err := tx.Commit(); err != nil {
		return nil, fmt.Errorf("提交事务失败: %w", err)
	}

	// 返回创建的群聊
	return &ConversationResponse{
		ID:            conv.ID,
		Type:          "group",
		Name:          name,
		Description:   description,
		AvatarURL:     avatarURL,
		CreatorID:     int64(creatorID),
		MemberCount:   len(memberIDs),
		CreatedAt:     conv.CreatedAt,
		UpdatedAt:     conv.UpdatedAt,
		LastMessageAt: &conv.LastMessageAt,
	}, nil
}

// UpdateConversation 更新会话信息
func UpdateConversation(ctx context.Context, conversationID int64, userID uint, name, description, avatarURL string) error {
	client := db.GetDBClient()

	// 获取会话
	conv, err := client.Conversation().Conversation.Get(ctx, conversationID)
	if err != nil {
		return fmt.Errorf("会话不存在: %w", err)
	}

	// 检查是否为群聊
	if conv.Type != conversation.TypeGroup {
		return fmt.Errorf("只能更新群聊信息")
	}

	// 检查权限（创建者或管理员才能更新）
	member, err := client.ConversationMember().ConversationMember.Query().
		Where(
			conversationmember.ConversationID(conversationID),
			conversationmember.UserID(int64(userID)),
		).
		Only(ctx)

	if err != nil {
		return fmt.Errorf("用户不是会话成员: %w", err)
	}

	if conv.CreatorID != int64(userID) && member.Role != "admin" && member.Role != "owner" {
		return fmt.Errorf("没有权限更新群聊信息")
	}

	// 创建更新构建器
	update := client.Conversation().Conversation.UpdateOneID(conversationID)

	// 添加需要更新的字段
	if name != "" {
		update = update.SetName(name)
	}

	if description != "" {
		update = update.SetDescription(description)
	}

	if avatarURL != "" {
		update = update.SetAvatarURL(avatarURL)
	}

	// 执行更新
	_, err = update.Save(ctx)
	return err
}

// DeleteConversation 删除会话
func DeleteConversation(ctx context.Context, conversationID int64, userID uint) error {
	client := db.GetDBClient()

	// 获取会话
	conv, err := client.Conversation().Conversation.Get(ctx, conversationID)
	if err != nil {
		return fmt.Errorf("会话不存在: %w", err)
	}

	// 检查权限
	if conv.Type == conversation.TypeGroup {
		// 对于群聊，只有创建者可以删除
		if conv.CreatorID != int64(userID) {
			return fmt.Errorf("只有群主可以删除群聊")
		}
	} else {
		// 对于私聊，检查用户是否是会话成员
		exists, err := client.ConversationMember().ConversationMember.Query().
			Where(
				conversationmember.ConversationID(conversationID),
				conversationmember.UserID(int64(userID)),
			).
			Exist(ctx)

		if err != nil || !exists {
			return fmt.Errorf("用户不是会话成员或会话不存在")
		}
	}

	// 开启事务
	tx, err := client.Group().Tx(ctx)
	if err != nil {
		return fmt.Errorf("开启事务失败: %w", err)
	}

	// 删除会话成员
	_, err = tx.ConversationMember.Delete().
		Where(conversationmember.ConversationID(conversationID)).
		Exec(ctx)

	if err != nil {
		tx.Rollback()
		return fmt.Errorf("删除会话成员失败: %w", err)
	}

	// 删除消息记录（可选，也可以保留历史记录）
	_, err = tx.Message.Delete().
		Where(message.ConversationID(conversationID)).
		Exec(ctx)

	if err != nil {
		tx.Rollback()
		return fmt.Errorf("删除消息记录失败: %w", err)
	}

	// 删除会话
	err = tx.Conversation.DeleteOneID(conversationID).Exec(ctx)
	if err != nil {
		tx.Rollback()
		return fmt.Errorf("删除会话失败: %w", err)
	}

	// 提交事务
	return tx.Commit()
}
